#!/bin/bash

: <<'COMMENT'
* 实时刷新、同时显示每个逻辑核心的「当前频率」+「使用率」+「温度」
* 完全基于系统自带文件，无需额外安装软件包
* 分页显示，一页显示20核心
* 支持超线程关闭时的温度匹配
* 食用方法：
    chmod +x cpu_monitor.sh
    ./cpu_monitor.sh
COMMENT

# 提示用户输入每页显示的核心数量
read -p "请输入每页显示的核心数量 (默认为20): " input_per_page
per_page=${input_per_page:-20}   # 每页核心总数
rows=10       # 每页行数（双列）
delta_f=10    # 频率变化阈值
delta_u=1     # 使用率变化阈值
sample_interval=1  # 采样间隔（秒）

# 颜色定义
GREEN_BRIGHT="\033[1;32m"  # 亮绿：频率下降/使用率下降（按需求定义的"好"变化）
RED_BRIGHT="\033[1;31m"    # 亮红：频率上升/使用率上升（按需求定义的"关注"变化）
GREEN_DIM="\033[0;32m"     # 暗绿：频率微小下降/使用率微小下降
RED_DIM="\033[0;31m"       # 暗红：频率微小上升/使用率微小上升
RESET="\033[0m"            # 重置颜色

# 初始化旧值存储
declare -A old_freq old_usage old_temp

# 温度变化阈值
delta_t=1     # 温度变化阈值

while :; do
    # 1. 获取CPU核心列表（用于排序）
    declare -A cores
    while read -r core _; do
        cores[$core]=1
    done < <(awk -F: '/^processor/{print $2, 1}' /proc/cpuinfo)
    mapfile -t sorted_cores < <(printf "%s\n" "${!cores[@]}" | sort -n)
    total_cores=${#sorted_cores[@]}

    # 2. 第一次采样CPU使用时间（计算使用率）
    declare -A user1 nice1 system1 idle1
    while read -r -a stats; do
        if [[ ${stats[0]} =~ ^cpu([0-9]+)$ ]]; then
            core=${BASH_REMATCH[1]}
            user1[$core]=${stats[1]}
            nice1[$core]=${stats[2]}
            system1[$core]=${stats[3]}
            idle1[$core]=${stats[4]}
        fi
    done < /proc/stat

    # 等待采样间隔
    sleep $sample_interval

    # 3. 第二次采样CPU使用时间
    declare -A user2 nice2 system2 idle2
    while read -r -a stats; do
        if [[ ${stats[0]} =~ ^cpu([0-9]+)$ ]]; then
            core=${BASH_REMATCH[1]}
            user2[$core]=${stats[1]}
            nice2[$core]=${stats[2]}
            system2[$core]=${stats[3]}
            idle2[$core]=${stats[4]}
        fi
    done < /proc/stat

    # 4. 获取当前频率、使用率和温度
    declare -A freq usage temp
    
    # 读取频率
    while read -r core mhz; do
        freq[$core]=$(printf "%.0f" "$mhz")
    done < <(awk -F: '/^processor/{c=$2} /^cpu MHz/{print c, $2}' /proc/cpuinfo)
    
    # 计算使用率（基于时间差）
    for core in "${!cores[@]}"; do
        if [[ -n "${user1[$core]}" && -n "${user2[$core]}" ]]; then
            u_diff=$((user2[$core] - user1[$core]))
            n_diff=$((nice2[$core] - nice1[$core]))
            s_diff=$((system2[$core] - system1[$core]))
            i_diff=$((idle2[$core] - idle1[$core]))
            total_diff=$((u_diff + n_diff + s_diff + i_diff))
            usage[$core]=$(( total_diff > 0 ? (total_diff - i_diff) * 100 / total_diff : 0 ))
        else
            usage[$core]=0
        fi
    done
    
    # 获取温度 - 建立逻辑CPU到物理核心的映射
    sensors_output=$(sensors 2>/dev/null)
    declare -A core_temp_map
    if [[ -n "$sensors_output" ]]; then
        # 解析sensors输出，提取每个物理核心的温度
        while IFS= read -r line; do
            if [[ $line =~ Core[[:space:]]([0-9]+):[^+]*\+([0-9]+)\. ]]; then
                core_num="${BASH_REMATCH[1]}"
                temp_val="${BASH_REMATCH[2]}"
                core_temp_map[$core_num]=$temp_val
            fi
        done <<< "$sensors_output"
    fi
    
    # 建立逻辑CPU到物理核心的映射
    declare -A cpu_to_core_map
    while IFS= read -r line; do
        if [[ $line =~ processor[[:space:]]*:[[:space:]]*([0-9]+) ]]; then
            current_cpu="${BASH_REMATCH[1]}"
        elif [[ $line =~ core[[:space:]]id[[:space:]]*:[[:space:]]*([0-9]+) ]]; then
            current_core="${BASH_REMATCH[1]}"
            cpu_to_core_map[$current_cpu]=$current_core
        fi
    done < /proc/cpuinfo
    
    # 将物理核心温度映射到逻辑CPU
    for core in "${!cores[@]}"; do
        if [[ -n "${cpu_to_core_map[$core]}" && -n "${core_temp_map[${cpu_to_core_map[$core]}]}" ]]; then
            temp[$core]="${core_temp_map[${cpu_to_core_map[$core]}]}"
        else
            temp[$core]=0
        fi
    done

    # 5. 分页双列显示
    total_pages=$(((total_cores + per_page - 1) / per_page))
    [[ $total_pages -eq 0 ]] && total_pages=1
    
    for ((page=0; page < total_pages; page++)); do
        clear
        start=$((page * per_page))
        end=$((start + per_page - 1))
        (( end >= total_cores )) && end=$((total_cores - 1))
        
        echo "CPU 监控（自定义颜色规则）- 第 $((page + 1))/$total_pages 页"
        echo "------------------------------------------------------------"
        echo "颜色规则：频率升/使用率升/温度升 → 红色"
        echo "颜色规则：频率降/使用率降/温度降 → 绿色"
        echo "------------------------------------------------------------"
        printf "%-3s %-6s %-4s %-4s   %-4s %-6s %-4s %-5s\n" \
               "核心" "频率" "使用率" "温度" "核心" "频率" "使用率" "温度"
        echo "------------------------------------------------------------"
        
        # 逐行显示双列数据
        for ((i=0; i < rows; i++)); do
            left_idx=$((start + i))
            right_idx=$((start + i + rows))
            
            # 左列处理
            if (( left_idx <= end )); then
                core_left=${sorted_cores[left_idx]}
                f_left=${freq[$core_left]}
                u_left=${usage[$core_left]}
                t_left=${temp[$core_left]}
                
                # 频率颜色（升→红，降→绿）
                f_color_left=""
                if [[ -n "${old_freq[$core_left]}" ]]; then
                    diff=$((f_left - old_freq[$core_left]))
                    if (( diff != 0 )); then
                        if (( diff > delta_f )); then
                            f_color_left=$RED_BRIGHT     # 频率显著上升→亮红
                        elif (( diff < -delta_f )); then
                            f_color_left=$GREEN_BRIGHT   # 频率显著下降→亮绿
                        elif (( diff > 0 )); then
                            f_color_left=$RED_DIM        # 频率微小上升→暗红
                        else
                            f_color_left=$GREEN_DIM      # 频率微小下降→暗绿
                        fi
                    fi
                fi
                
                # 使用率颜色（升→红，降→绿）
                u_color_left=""
                if [[ -n "${old_usage[$core_left]}" ]]; then
                    diff=$((u_left - old_usage[$core_left]))
                    if (( diff != 0 )); then
                        if (( diff > delta_u )); then
                            u_color_left=$RED_BRIGHT     # 使用率显著上升→亮红
                        elif (( diff < -delta_u )); then
                            u_color_left=$GREEN_BRIGHT   # 使用率显著下降→亮绿
                        elif (( diff > 0 )); then
                            u_color_left=$RED_DIM        # 使用率微小上升→暗红
                        else
                            u_color_left=$GREEN_DIM      # 使用率微小下降→暗绿
                        fi
                    fi
                fi

                # 温度颜色（升→红，降→绿）
                t_color_left=""
                if [[ -n "${old_temp[$core_left]}" && ${t_left} -gt 0 ]]; then
                    diff=$((t_left - old_temp[$core_left]))
                    if (( diff != 0 )); then
                        if (( diff > delta_t )); then
                            t_color_left=$RED_BRIGHT     # 温度显著上升→亮红
                        elif (( diff < -delta_t )); then
                            t_color_left=$GREEN_BRIGHT   # 温度显著下降→亮绿
                        elif (( diff > 0 )); then
                            t_color_left=$RED_DIM        # 温度微小上升→暗红
                        else
                            t_color_left=$GREEN_DIM      # 温度微小下降→暗绿
                        fi
                    fi
                fi
                
                # 输出左列
                printf "%-3s " "$core_left"
                printf "${f_color_left}%-6s${RESET} " "$f_left"
                printf "${u_color_left}%-4s${RESET} " "${u_left}%"
                printf "${t_color_left}%-4s${RESET}" "${t_left}°C"
            else
                printf "%-3s %-6s %-4s %-5s" "" "" "" ""
            fi
            
            # 列间距
            printf "    "
            
            # 右列处理（逻辑同左列）
            if (( right_idx <= end )); then
                core_right=${sorted_cores[right_idx]}
                f_right=${freq[$core_right]}
                u_right=${usage[$core_right]}
                t_right=${temp[$core_right]}
                
                # 频率颜色
                f_color_right=""
                if [[ -n "${old_freq[$core_right]}" ]]; then
                    diff=$((f_right - old_freq[$core_right]))
                    if (( diff != 0 )); then
                        if (( diff > delta_f )); then
                            f_color_right=$RED_BRIGHT
                        elif (( diff < -delta_f )); then
                            f_color_right=$GREEN_BRIGHT
                        elif (( diff > 0 )); then
                            f_color_right=$RED_DIM
                        else
                            f_color_right=$GREEN_DIM
                        fi
                    fi
                fi
                
                # 使用率颜色
                u_color_right=""
                if [[ -n "${old_usage[$core_right]}" ]]; then
                    diff=$((u_right - old_usage[$core_right]))
                    if (( diff != 0 )); then
                        if (( diff > delta_u )); then
                            u_color_right=$RED_BRIGHT
                        elif (( diff < -delta_u )); then
                            u_color_right=$GREEN_BRIGHT
                        elif (( diff > 0 )); then
                            u_color_right=$RED_DIM
                        else
                            u_color_right=$GREEN_DIM
                        fi
                    fi
                fi

                # 温度颜色
                t_color_right=""
                if [[ -n "${old_temp[$core_right]}" && ${t_right} -gt 0 ]]; then
                    diff=$((t_right - old_temp[$core_right]))
                    if (( diff != 0 )); then
                        if (( diff > delta_t )); then
                            t_color_right=$RED_BRIGHT
                        elif (( diff < -delta_t )); then
                            t_color_right=$GREEN_BRIGHT
                        elif (( diff > 0 )); then
                            t_color_right=$RED_DIM
                        else
                            t_color_right=$GREEN_DIM
                        fi
                    fi
                fi
                
                # 输出右列
                printf "%-3s " "$core_right"
                printf "${f_color_right}%-6s${RESET} " "$f_right"
                printf "${u_color_right}%-4s${RESET} " "${u_right}%"
                printf "${t_color_right}%-4s${RESET}" "${t_right}°C"
            else
                printf "%-3s %-6s %-4s %-4s" "" "" "" ""
            fi
            
            printf "\n"
        done
        
        echo "------------------------------------------------------------"
        echo "亮色：变化超过阈值 | 暗色：微小变化 | 1秒后刷新"
        sleep 1
    done
    
    # 6. 更新旧值（供下次对比）
    for core in "${!freq[@]}"; do
        old_freq[$core]=${freq[$core]}
        old_usage[$core]=${usage[$core]}
        old_temp[$core]=${temp[$core]}
    done
done